/**
 * This file is part of the "Learn WebGPU for C++" book.
 *   https://github.com/eliemichel/LearnWebGPU
 *
 * MIT License
 * Copyright (c) 2022 Elie Michel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * Exactly one of your source files must #define WEBGPU_CPP_IMPLEMENTATION
 * before including this header.
 * 
 * NB: This file has been generated by the webgpu-cpp generator
 *   (see https://github.com/eliemichel/webgpu-cpp )
 */

#pragma once

#include <webgpu/webgpu.h>

#include <iostream>
#include <vector>
#include <functional>
#include <cassert>
#include <memory>

/**
 * A namespace providing a more C++ idiomatic API to WebGPU.
 */
namespace wgpu {

struct DefaultFlag {};
constexpr DefaultFlag Default;

#define HANDLE(Type) \
class Type { \
public: \
	typedef Type S; /* S == Self */ \
	typedef WGPU ## Type W; /* W == WGPU Type */ \
	Type(const W& w) : m_raw(w) {} \
	operator W&() { return m_raw; } \
	operator const W&() const { return m_raw; } \
	operator bool() const { return m_raw != nullptr; } \
	friend auto operator<<(std::ostream &stream, const S& self) -> std::ostream & { \
		return stream << "<wgpu::" << #Type << " " << self.m_raw << ">"; \
	} \
private: \
	W m_raw; \
public:

#define DESCRIPTOR(Type) \
struct Type : public WGPU ## Type { \
public: \
	typedef Type S; /* S == Self */ \
	typedef WGPU ## Type W; /* W == WGPU Type */ \
	Type() : W() { nextInChain = nullptr; } \
	Type(const W &other) : W(other) { nextInChain = nullptr; } \
	Type(const DefaultFlag &) : W() { setDefault(); } \
	Type& operator=(const DefaultFlag &) { setDefault(); return *this; } \
	friend auto operator<<(std::ostream &stream, const S&) -> std::ostream & { \
		return stream << "<wgpu::" << #Type << ">"; \
	} \
public:

#define STRUCT(Type) \
struct Type : public WGPU ## Type { \
public: \
	typedef Type S; /* S == Self */ \
	typedef WGPU ## Type W; /* W == WGPU Type */ \
	Type() : W() {} \
	Type(const W &other) : W(other) {} \
	Type(const DefaultFlag &) : W() { setDefault(); } \
	Type& operator=(const DefaultFlag &) { setDefault(); return *this; } \
	friend auto operator<<(std::ostream &stream, const S&) -> std::ostream & { \
		return stream << "<wgpu::" << #Type << ">"; \
	} \
public:

#define ENUM(Type) \
class Type { \
public: \
	typedef Type S; /* S == Self */ \
	typedef WGPU ## Type W; /* W == WGPU Type */ \
	Type(const W& w) : m_raw(w) {} \
	operator W() const { return m_raw; } \
private: \
	W m_raw; \
public:

#define ENUM_ENTRY(Name, Value) \
	static constexpr W Name = (W)Value;

#define END };



// Enumerations
ENUM(AdapterType)
	ENUM_ENTRY(DiscreteGPU, 0x00000000)
	ENUM_ENTRY(IntegratedGPU, 0x00000001)
	ENUM_ENTRY(CPU, 0x00000002)
	ENUM_ENTRY(Unknown, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(AddressMode)
	ENUM_ENTRY(Repeat, 0x00000000)
	ENUM_ENTRY(MirrorRepeat, 0x00000001)
	ENUM_ENTRY(ClampToEdge, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BackendType)
	ENUM_ENTRY(Null, 0x00000000)
	ENUM_ENTRY(WebGPU, 0x00000001)
	ENUM_ENTRY(D3D11, 0x00000002)
	ENUM_ENTRY(D3D12, 0x00000003)
	ENUM_ENTRY(Metal, 0x00000004)
	ENUM_ENTRY(Vulkan, 0x00000005)
	ENUM_ENTRY(OpenGL, 0x00000006)
	ENUM_ENTRY(OpenGLES, 0x00000007)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BlendFactor)
	ENUM_ENTRY(Zero, 0x00000000)
	ENUM_ENTRY(One, 0x00000001)
	ENUM_ENTRY(Src, 0x00000002)
	ENUM_ENTRY(OneMinusSrc, 0x00000003)
	ENUM_ENTRY(SrcAlpha, 0x00000004)
	ENUM_ENTRY(OneMinusSrcAlpha, 0x00000005)
	ENUM_ENTRY(Dst, 0x00000006)
	ENUM_ENTRY(OneMinusDst, 0x00000007)
	ENUM_ENTRY(DstAlpha, 0x00000008)
	ENUM_ENTRY(OneMinusDstAlpha, 0x00000009)
	ENUM_ENTRY(SrcAlphaSaturated, 0x0000000A)
	ENUM_ENTRY(Constant, 0x0000000B)
	ENUM_ENTRY(OneMinusConstant, 0x0000000C)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BlendOperation)
	ENUM_ENTRY(Add, 0x00000000)
	ENUM_ENTRY(Subtract, 0x00000001)
	ENUM_ENTRY(ReverseSubtract, 0x00000002)
	ENUM_ENTRY(Min, 0x00000003)
	ENUM_ENTRY(Max, 0x00000004)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BufferBindingType)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Uniform, 0x00000001)
	ENUM_ENTRY(Storage, 0x00000002)
	ENUM_ENTRY(ReadOnlyStorage, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BufferMapAsyncStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(Error, 0x00000001)
	ENUM_ENTRY(Unknown, 0x00000002)
	ENUM_ENTRY(DeviceLost, 0x00000003)
	ENUM_ENTRY(DestroyedBeforeCallback, 0x00000004)
	ENUM_ENTRY(UnmappedBeforeCallback, 0x00000005)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BufferMapState)
	ENUM_ENTRY(Unmapped, 0x00000000)
	ENUM_ENTRY(Pending, 0x00000001)
	ENUM_ENTRY(Mapped, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(CompareFunction)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Never, 0x00000001)
	ENUM_ENTRY(Less, 0x00000002)
	ENUM_ENTRY(LessEqual, 0x00000003)
	ENUM_ENTRY(Greater, 0x00000004)
	ENUM_ENTRY(GreaterEqual, 0x00000005)
	ENUM_ENTRY(Equal, 0x00000006)
	ENUM_ENTRY(NotEqual, 0x00000007)
	ENUM_ENTRY(Always, 0x00000008)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(CompilationInfoRequestStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(Error, 0x00000001)
	ENUM_ENTRY(DeviceLost, 0x00000002)
	ENUM_ENTRY(Unknown, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(CompilationMessageType)
	ENUM_ENTRY(Error, 0x00000000)
	ENUM_ENTRY(Warning, 0x00000001)
	ENUM_ENTRY(Info, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(ComputePassTimestampLocation)
	ENUM_ENTRY(Beginning, 0x00000000)
	ENUM_ENTRY(End, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(CreatePipelineAsyncStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(ValidationError, 0x00000001)
	ENUM_ENTRY(InternalError, 0x00000002)
	ENUM_ENTRY(DeviceLost, 0x00000003)
	ENUM_ENTRY(DeviceDestroyed, 0x00000004)
	ENUM_ENTRY(Unknown, 0x00000005)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(CullMode)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(Front, 0x00000001)
	ENUM_ENTRY(Back, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(DeviceLostReason)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Destroyed, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(ErrorFilter)
	ENUM_ENTRY(Validation, 0x00000000)
	ENUM_ENTRY(OutOfMemory, 0x00000001)
	ENUM_ENTRY(Internal, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(ErrorType)
	ENUM_ENTRY(NoError, 0x00000000)
	ENUM_ENTRY(Validation, 0x00000001)
	ENUM_ENTRY(OutOfMemory, 0x00000002)
	ENUM_ENTRY(Internal, 0x00000003)
	ENUM_ENTRY(Unknown, 0x00000004)
	ENUM_ENTRY(DeviceLost, 0x00000005)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(FeatureName)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(DepthClipControl, 0x00000001)
	ENUM_ENTRY(Depth32FloatStencil8, 0x00000002)
	ENUM_ENTRY(TimestampQuery, 0x00000003)
	ENUM_ENTRY(PipelineStatisticsQuery, 0x00000004)
	ENUM_ENTRY(TextureCompressionBC, 0x00000005)
	ENUM_ENTRY(TextureCompressionETC2, 0x00000006)
	ENUM_ENTRY(TextureCompressionASTC, 0x00000007)
	ENUM_ENTRY(IndirectFirstInstance, 0x00000008)
	ENUM_ENTRY(ShaderF16, 0x00000009)
	ENUM_ENTRY(RG11B10UfloatRenderable, 0x0000000A)
	ENUM_ENTRY(BGRA8UnormStorage, 0x0000000B)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(FilterMode)
	ENUM_ENTRY(Nearest, 0x00000000)
	ENUM_ENTRY(Linear, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(FrontFace)
	ENUM_ENTRY(CCW, 0x00000000)
	ENUM_ENTRY(CW, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(IndexFormat)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Uint16, 0x00000001)
	ENUM_ENTRY(Uint32, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(LoadOp)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Clear, 0x00000001)
	ENUM_ENTRY(Load, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(MipmapFilterMode)
	ENUM_ENTRY(Nearest, 0x00000000)
	ENUM_ENTRY(Linear, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(PipelineStatisticName)
	ENUM_ENTRY(VertexShaderInvocations, 0x00000000)
	ENUM_ENTRY(ClipperInvocations, 0x00000001)
	ENUM_ENTRY(ClipperPrimitivesOut, 0x00000002)
	ENUM_ENTRY(FragmentShaderInvocations, 0x00000003)
	ENUM_ENTRY(ComputeShaderInvocations, 0x00000004)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(PowerPreference)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(LowPower, 0x00000001)
	ENUM_ENTRY(HighPerformance, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(PresentMode)
	ENUM_ENTRY(Immediate, 0x00000000)
	ENUM_ENTRY(Mailbox, 0x00000001)
	ENUM_ENTRY(Fifo, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(PrimitiveTopology)
	ENUM_ENTRY(PointList, 0x00000000)
	ENUM_ENTRY(LineList, 0x00000001)
	ENUM_ENTRY(LineStrip, 0x00000002)
	ENUM_ENTRY(TriangleList, 0x00000003)
	ENUM_ENTRY(TriangleStrip, 0x00000004)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(QueryType)
	ENUM_ENTRY(Occlusion, 0x00000000)
	ENUM_ENTRY(PipelineStatistics, 0x00000001)
	ENUM_ENTRY(Timestamp, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(QueueWorkDoneStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(Error, 0x00000001)
	ENUM_ENTRY(Unknown, 0x00000002)
	ENUM_ENTRY(DeviceLost, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(RenderPassTimestampLocation)
	ENUM_ENTRY(Beginning, 0x00000000)
	ENUM_ENTRY(End, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(RequestAdapterStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(Unavailable, 0x00000001)
	ENUM_ENTRY(Error, 0x00000002)
	ENUM_ENTRY(Unknown, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(RequestDeviceStatus)
	ENUM_ENTRY(Success, 0x00000000)
	ENUM_ENTRY(Error, 0x00000001)
	ENUM_ENTRY(Unknown, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(SType)
	ENUM_ENTRY(Invalid, 0x00000000)
	ENUM_ENTRY(SurfaceDescriptorFromMetalLayer, 0x00000001)
	ENUM_ENTRY(SurfaceDescriptorFromWindowsHWND, 0x00000002)
	ENUM_ENTRY(SurfaceDescriptorFromXlibWindow, 0x00000003)
	ENUM_ENTRY(SurfaceDescriptorFromCanvasHTMLSelector, 0x00000004)
	ENUM_ENTRY(ShaderModuleSPIRVDescriptor, 0x00000005)
	ENUM_ENTRY(ShaderModuleWGSLDescriptor, 0x00000006)
	ENUM_ENTRY(PrimitiveDepthClipControl, 0x00000007)
	ENUM_ENTRY(SurfaceDescriptorFromWaylandSurface, 0x00000008)
	ENUM_ENTRY(SurfaceDescriptorFromAndroidNativeWindow, 0x00000009)
	ENUM_ENTRY(SurfaceDescriptorFromXcbWindow, 0x0000000A)
	ENUM_ENTRY(RenderPassDescriptorMaxDrawCount, 0x0000000F)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(SamplerBindingType)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Filtering, 0x00000001)
	ENUM_ENTRY(NonFiltering, 0x00000002)
	ENUM_ENTRY(Comparison, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(StencilOperation)
	ENUM_ENTRY(Keep, 0x00000000)
	ENUM_ENTRY(Zero, 0x00000001)
	ENUM_ENTRY(Replace, 0x00000002)
	ENUM_ENTRY(Invert, 0x00000003)
	ENUM_ENTRY(IncrementClamp, 0x00000004)
	ENUM_ENTRY(DecrementClamp, 0x00000005)
	ENUM_ENTRY(IncrementWrap, 0x00000006)
	ENUM_ENTRY(DecrementWrap, 0x00000007)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(StorageTextureAccess)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(WriteOnly, 0x00000001)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(StoreOp)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Store, 0x00000001)
	ENUM_ENTRY(Discard, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureAspect)
	ENUM_ENTRY(All, 0x00000000)
	ENUM_ENTRY(StencilOnly, 0x00000001)
	ENUM_ENTRY(DepthOnly, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureComponentType)
	ENUM_ENTRY(Float, 0x00000000)
	ENUM_ENTRY(Sint, 0x00000001)
	ENUM_ENTRY(Uint, 0x00000002)
	ENUM_ENTRY(DepthComparison, 0x00000003)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureDimension)
	ENUM_ENTRY(_1D, 0x00000000)
	ENUM_ENTRY(_2D, 0x00000001)
	ENUM_ENTRY(_3D, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureFormat)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(R8Unorm, 0x00000001)
	ENUM_ENTRY(R8Snorm, 0x00000002)
	ENUM_ENTRY(R8Uint, 0x00000003)
	ENUM_ENTRY(R8Sint, 0x00000004)
	ENUM_ENTRY(R16Uint, 0x00000005)
	ENUM_ENTRY(R16Sint, 0x00000006)
	ENUM_ENTRY(R16Float, 0x00000007)
	ENUM_ENTRY(RG8Unorm, 0x00000008)
	ENUM_ENTRY(RG8Snorm, 0x00000009)
	ENUM_ENTRY(RG8Uint, 0x0000000A)
	ENUM_ENTRY(RG8Sint, 0x0000000B)
	ENUM_ENTRY(R32Float, 0x0000000C)
	ENUM_ENTRY(R32Uint, 0x0000000D)
	ENUM_ENTRY(R32Sint, 0x0000000E)
	ENUM_ENTRY(RG16Uint, 0x0000000F)
	ENUM_ENTRY(RG16Sint, 0x00000010)
	ENUM_ENTRY(RG16Float, 0x00000011)
	ENUM_ENTRY(RGBA8Unorm, 0x00000012)
	ENUM_ENTRY(RGBA8UnormSrgb, 0x00000013)
	ENUM_ENTRY(RGBA8Snorm, 0x00000014)
	ENUM_ENTRY(RGBA8Uint, 0x00000015)
	ENUM_ENTRY(RGBA8Sint, 0x00000016)
	ENUM_ENTRY(BGRA8Unorm, 0x00000017)
	ENUM_ENTRY(BGRA8UnormSrgb, 0x00000018)
	ENUM_ENTRY(RGB10A2Unorm, 0x00000019)
	ENUM_ENTRY(RG11B10Ufloat, 0x0000001A)
	ENUM_ENTRY(RGB9E5Ufloat, 0x0000001B)
	ENUM_ENTRY(RG32Float, 0x0000001C)
	ENUM_ENTRY(RG32Uint, 0x0000001D)
	ENUM_ENTRY(RG32Sint, 0x0000001E)
	ENUM_ENTRY(RGBA16Uint, 0x0000001F)
	ENUM_ENTRY(RGBA16Sint, 0x00000020)
	ENUM_ENTRY(RGBA16Float, 0x00000021)
	ENUM_ENTRY(RGBA32Float, 0x00000022)
	ENUM_ENTRY(RGBA32Uint, 0x00000023)
	ENUM_ENTRY(RGBA32Sint, 0x00000024)
	ENUM_ENTRY(Stencil8, 0x00000025)
	ENUM_ENTRY(Depth16Unorm, 0x00000026)
	ENUM_ENTRY(Depth24Plus, 0x00000027)
	ENUM_ENTRY(Depth24PlusStencil8, 0x00000028)
	ENUM_ENTRY(Depth32Float, 0x00000029)
	ENUM_ENTRY(Depth32FloatStencil8, 0x0000002A)
	ENUM_ENTRY(BC1RGBAUnorm, 0x0000002B)
	ENUM_ENTRY(BC1RGBAUnormSrgb, 0x0000002C)
	ENUM_ENTRY(BC2RGBAUnorm, 0x0000002D)
	ENUM_ENTRY(BC2RGBAUnormSrgb, 0x0000002E)
	ENUM_ENTRY(BC3RGBAUnorm, 0x0000002F)
	ENUM_ENTRY(BC3RGBAUnormSrgb, 0x00000030)
	ENUM_ENTRY(BC4RUnorm, 0x00000031)
	ENUM_ENTRY(BC4RSnorm, 0x00000032)
	ENUM_ENTRY(BC5RGUnorm, 0x00000033)
	ENUM_ENTRY(BC5RGSnorm, 0x00000034)
	ENUM_ENTRY(BC6HRGBUfloat, 0x00000035)
	ENUM_ENTRY(BC6HRGBFloat, 0x00000036)
	ENUM_ENTRY(BC7RGBAUnorm, 0x00000037)
	ENUM_ENTRY(BC7RGBAUnormSrgb, 0x00000038)
	ENUM_ENTRY(ETC2RGB8Unorm, 0x00000039)
	ENUM_ENTRY(ETC2RGB8UnormSrgb, 0x0000003A)
	ENUM_ENTRY(ETC2RGB8A1Unorm, 0x0000003B)
	ENUM_ENTRY(ETC2RGB8A1UnormSrgb, 0x0000003C)
	ENUM_ENTRY(ETC2RGBA8Unorm, 0x0000003D)
	ENUM_ENTRY(ETC2RGBA8UnormSrgb, 0x0000003E)
	ENUM_ENTRY(EACR11Unorm, 0x0000003F)
	ENUM_ENTRY(EACR11Snorm, 0x00000040)
	ENUM_ENTRY(EACRG11Unorm, 0x00000041)
	ENUM_ENTRY(EACRG11Snorm, 0x00000042)
	ENUM_ENTRY(ASTC4x4Unorm, 0x00000043)
	ENUM_ENTRY(ASTC4x4UnormSrgb, 0x00000044)
	ENUM_ENTRY(ASTC5x4Unorm, 0x00000045)
	ENUM_ENTRY(ASTC5x4UnormSrgb, 0x00000046)
	ENUM_ENTRY(ASTC5x5Unorm, 0x00000047)
	ENUM_ENTRY(ASTC5x5UnormSrgb, 0x00000048)
	ENUM_ENTRY(ASTC6x5Unorm, 0x00000049)
	ENUM_ENTRY(ASTC6x5UnormSrgb, 0x0000004A)
	ENUM_ENTRY(ASTC6x6Unorm, 0x0000004B)
	ENUM_ENTRY(ASTC6x6UnormSrgb, 0x0000004C)
	ENUM_ENTRY(ASTC8x5Unorm, 0x0000004D)
	ENUM_ENTRY(ASTC8x5UnormSrgb, 0x0000004E)
	ENUM_ENTRY(ASTC8x6Unorm, 0x0000004F)
	ENUM_ENTRY(ASTC8x6UnormSrgb, 0x00000050)
	ENUM_ENTRY(ASTC8x8Unorm, 0x00000051)
	ENUM_ENTRY(ASTC8x8UnormSrgb, 0x00000052)
	ENUM_ENTRY(ASTC10x5Unorm, 0x00000053)
	ENUM_ENTRY(ASTC10x5UnormSrgb, 0x00000054)
	ENUM_ENTRY(ASTC10x6Unorm, 0x00000055)
	ENUM_ENTRY(ASTC10x6UnormSrgb, 0x00000056)
	ENUM_ENTRY(ASTC10x8Unorm, 0x00000057)
	ENUM_ENTRY(ASTC10x8UnormSrgb, 0x00000058)
	ENUM_ENTRY(ASTC10x10Unorm, 0x00000059)
	ENUM_ENTRY(ASTC10x10UnormSrgb, 0x0000005A)
	ENUM_ENTRY(ASTC12x10Unorm, 0x0000005B)
	ENUM_ENTRY(ASTC12x10UnormSrgb, 0x0000005C)
	ENUM_ENTRY(ASTC12x12Unorm, 0x0000005D)
	ENUM_ENTRY(ASTC12x12UnormSrgb, 0x0000005E)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureSampleType)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Float, 0x00000001)
	ENUM_ENTRY(UnfilterableFloat, 0x00000002)
	ENUM_ENTRY(Depth, 0x00000003)
	ENUM_ENTRY(Sint, 0x00000004)
	ENUM_ENTRY(Uint, 0x00000005)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureViewDimension)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(_1D, 0x00000001)
	ENUM_ENTRY(_2D, 0x00000002)
	ENUM_ENTRY(_2DArray, 0x00000003)
	ENUM_ENTRY(Cube, 0x00000004)
	ENUM_ENTRY(CubeArray, 0x00000005)
	ENUM_ENTRY(_3D, 0x00000006)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(VertexFormat)
	ENUM_ENTRY(Undefined, 0x00000000)
	ENUM_ENTRY(Uint8x2, 0x00000001)
	ENUM_ENTRY(Uint8x4, 0x00000002)
	ENUM_ENTRY(Sint8x2, 0x00000003)
	ENUM_ENTRY(Sint8x4, 0x00000004)
	ENUM_ENTRY(Unorm8x2, 0x00000005)
	ENUM_ENTRY(Unorm8x4, 0x00000006)
	ENUM_ENTRY(Snorm8x2, 0x00000007)
	ENUM_ENTRY(Snorm8x4, 0x00000008)
	ENUM_ENTRY(Uint16x2, 0x00000009)
	ENUM_ENTRY(Uint16x4, 0x0000000A)
	ENUM_ENTRY(Sint16x2, 0x0000000B)
	ENUM_ENTRY(Sint16x4, 0x0000000C)
	ENUM_ENTRY(Unorm16x2, 0x0000000D)
	ENUM_ENTRY(Unorm16x4, 0x0000000E)
	ENUM_ENTRY(Snorm16x2, 0x0000000F)
	ENUM_ENTRY(Snorm16x4, 0x00000010)
	ENUM_ENTRY(Float16x2, 0x00000011)
	ENUM_ENTRY(Float16x4, 0x00000012)
	ENUM_ENTRY(Float32, 0x00000013)
	ENUM_ENTRY(Float32x2, 0x00000014)
	ENUM_ENTRY(Float32x3, 0x00000015)
	ENUM_ENTRY(Float32x4, 0x00000016)
	ENUM_ENTRY(Uint32, 0x00000017)
	ENUM_ENTRY(Uint32x2, 0x00000018)
	ENUM_ENTRY(Uint32x3, 0x00000019)
	ENUM_ENTRY(Uint32x4, 0x0000001A)
	ENUM_ENTRY(Sint32, 0x0000001B)
	ENUM_ENTRY(Sint32x2, 0x0000001C)
	ENUM_ENTRY(Sint32x3, 0x0000001D)
	ENUM_ENTRY(Sint32x4, 0x0000001E)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(VertexStepMode)
	ENUM_ENTRY(Vertex, 0x00000000)
	ENUM_ENTRY(Instance, 0x00000001)
	ENUM_ENTRY(VertexBufferNotUsed, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BufferUsage)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(MapRead, 0x00000001)
	ENUM_ENTRY(MapWrite, 0x00000002)
	ENUM_ENTRY(CopySrc, 0x00000004)
	ENUM_ENTRY(CopyDst, 0x00000008)
	ENUM_ENTRY(Index, 0x00000010)
	ENUM_ENTRY(Vertex, 0x00000020)
	ENUM_ENTRY(Uniform, 0x00000040)
	ENUM_ENTRY(Storage, 0x00000080)
	ENUM_ENTRY(Indirect, 0x00000100)
	ENUM_ENTRY(QueryResolve, 0x00000200)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(BufferUsageFlags)
END
ENUM(ColorWriteMask)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(Red, 0x00000001)
	ENUM_ENTRY(Green, 0x00000002)
	ENUM_ENTRY(Blue, 0x00000004)
	ENUM_ENTRY(Alpha, 0x00000008)
	ENUM_ENTRY(All, 0x0000000F)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(ColorWriteMaskFlags)
END
ENUM(MapMode)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(Read, 0x00000001)
	ENUM_ENTRY(Write, 0x00000002)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(MapModeFlags)
END
ENUM(ShaderStage)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(Vertex, 0x00000001)
	ENUM_ENTRY(Fragment, 0x00000002)
	ENUM_ENTRY(Compute, 0x00000004)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(ShaderStageFlags)
END
ENUM(TextureUsage)
	ENUM_ENTRY(None, 0x00000000)
	ENUM_ENTRY(CopySrc, 0x00000001)
	ENUM_ENTRY(CopyDst, 0x00000002)
	ENUM_ENTRY(TextureBinding, 0x00000004)
	ENUM_ENTRY(StorageBinding, 0x00000008)
	ENUM_ENTRY(RenderAttachment, 0x00000010)
	ENUM_ENTRY(Force32, 0x7FFFFFFF)
END
ENUM(TextureUsageFlags)
END

// Structs
STRUCT(ChainedStruct)
	void setDefault();
END

STRUCT(ChainedStructOut)
	void setDefault();
END

STRUCT(BlendComponent)
	void setDefault();
END

STRUCT(Color)
	Color(double r, double g, double b, double a) : WGPUColor{ r, g, b, a } {}
	void setDefault();
END

STRUCT(ComputePassTimestampWrite)
	void setDefault();
END

STRUCT(Extent3D)
	Extent3D(uint32_t width, uint32_t height, uint32_t depthOrArrayLayers) : WGPUExtent3D{ width, height, depthOrArrayLayers } {}
	void setDefault();
END

STRUCT(Limits)
	void setDefault();
END

STRUCT(Origin3D)
	Origin3D(uint32_t x, uint32_t y, uint32_t z) : WGPUOrigin3D{ x, y, z } {}
	void setDefault();
END

STRUCT(PrimitiveDepthClipControl)
	void setDefault();
END

STRUCT(RenderPassDepthStencilAttachment)
	void setDefault();
END

STRUCT(RenderPassDescriptorMaxDrawCount)
	void setDefault();
END

STRUCT(RenderPassTimestampWrite)
	void setDefault();
END

STRUCT(ShaderModuleSPIRVDescriptor)
	void setDefault();
END

STRUCT(ShaderModuleWGSLDescriptor)
	void setDefault();
END

STRUCT(StencilFaceState)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromAndroidNativeWindow)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromCanvasHTMLSelector)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromMetalLayer)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromWaylandSurface)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromWindowsHWND)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromXcbWindow)
	void setDefault();
END

STRUCT(SurfaceDescriptorFromXlibWindow)
	void setDefault();
END

STRUCT(VertexAttribute)
	void setDefault();
END

STRUCT(BlendState)
	void setDefault();
END

STRUCT(RenderPassColorAttachment)
	void setDefault();
END

STRUCT(VertexBufferLayout)
	void setDefault();
END


// Descriptors
DESCRIPTOR(AdapterProperties)
	void setDefault();
END

DESCRIPTOR(BindGroupEntry)
	void setDefault();
END

DESCRIPTOR(BufferBindingLayout)
	void setDefault();
END

DESCRIPTOR(BufferDescriptor)
	void setDefault();
END

DESCRIPTOR(CommandBufferDescriptor)
	void setDefault();
END

DESCRIPTOR(CommandEncoderDescriptor)
	void setDefault();
END

DESCRIPTOR(CompilationMessage)
	void setDefault();
END

DESCRIPTOR(ConstantEntry)
	void setDefault();
END

DESCRIPTOR(InstanceDescriptor)
	void setDefault();
END

DESCRIPTOR(MultisampleState)
	void setDefault();
END

DESCRIPTOR(PipelineLayoutDescriptor)
	void setDefault();
END

DESCRIPTOR(PrimitiveState)
	void setDefault();
END

DESCRIPTOR(QuerySetDescriptor)
	void setDefault();
END

DESCRIPTOR(QueueDescriptor)
	void setDefault();
END

DESCRIPTOR(RenderBundleDescriptor)
	void setDefault();
END

DESCRIPTOR(RenderBundleEncoderDescriptor)
	void setDefault();
END

DESCRIPTOR(RequestAdapterOptions)
	void setDefault();
END

DESCRIPTOR(SamplerBindingLayout)
	void setDefault();
END

DESCRIPTOR(SamplerDescriptor)
	void setDefault();
END

DESCRIPTOR(ShaderModuleCompilationHint)
	void setDefault();
END

DESCRIPTOR(StorageTextureBindingLayout)
	void setDefault();
END

DESCRIPTOR(SurfaceDescriptor)
	void setDefault();
END

DESCRIPTOR(SwapChainDescriptor)
	void setDefault();
END

DESCRIPTOR(TextureBindingLayout)
	void setDefault();
END

DESCRIPTOR(TextureDataLayout)
	void setDefault();
END

DESCRIPTOR(TextureViewDescriptor)
	void setDefault();
END

DESCRIPTOR(BindGroupDescriptor)
	void setDefault();
END

DESCRIPTOR(BindGroupLayoutEntry)
	void setDefault();
END

DESCRIPTOR(CompilationInfo)
	void setDefault();
END

DESCRIPTOR(ComputePassDescriptor)
	void setDefault();
END

DESCRIPTOR(DepthStencilState)
	void setDefault();
END

DESCRIPTOR(ImageCopyBuffer)
	void setDefault();
END

DESCRIPTOR(ImageCopyTexture)
	void setDefault();
END

DESCRIPTOR(ProgrammableStageDescriptor)
	void setDefault();
END

DESCRIPTOR(RequiredLimits)
	void setDefault();
END

DESCRIPTOR(ShaderModuleDescriptor)
	void setDefault();
END

DESCRIPTOR(SupportedLimits)
	void setDefault();
END

DESCRIPTOR(TextureDescriptor)
	void setDefault();
END

DESCRIPTOR(BindGroupLayoutDescriptor)
	void setDefault();
END

DESCRIPTOR(ColorTargetState)
	void setDefault();
END

DESCRIPTOR(ComputePipelineDescriptor)
	void setDefault();
END

DESCRIPTOR(DeviceDescriptor)
	void setDefault();
END

DESCRIPTOR(RenderPassDescriptor)
	void setDefault();
END

DESCRIPTOR(VertexState)
	void setDefault();
END

DESCRIPTOR(FragmentState)
	void setDefault();
END

DESCRIPTOR(RenderPipelineDescriptor)
	void setDefault();
END


// Handles forward declarations
class Adapter;
class BindGroup;
class BindGroupLayout;
class Buffer;
class CommandBuffer;
class CommandEncoder;
class ComputePassEncoder;
class ComputePipeline;
class Device;
class Instance;
class PipelineLayout;
class QuerySet;
class Queue;
class RenderBundle;
class RenderBundleEncoder;
class RenderPassEncoder;
class RenderPipeline;
class Sampler;
class ShaderModule;
class Surface;
class SwapChain;
class Texture;
class TextureView;

// Callback types
using BufferMapCallback = std::function<void(BufferMapAsyncStatus status)>;
using CompilationInfoCallback = std::function<void(CompilationInfoRequestStatus status, const CompilationInfo& compilationInfo)>;
using CreateComputePipelineAsyncCallback = std::function<void(CreatePipelineAsyncStatus status, ComputePipeline pipeline, char const * message)>;
using CreateRenderPipelineAsyncCallback = std::function<void(CreatePipelineAsyncStatus status, RenderPipeline pipeline, char const * message)>;
using DeviceLostCallback = std::function<void(DeviceLostReason reason, char const * message)>;
using ErrorCallback = std::function<void(ErrorType type, char const * message)>;
using QueueWorkDoneCallback = std::function<void(QueueWorkDoneStatus status)>;
using RequestAdapterCallback = std::function<void(RequestAdapterStatus status, Adapter adapter, char const * message)>;
using RequestDeviceCallback = std::function<void(RequestDeviceStatus status, Device device, char const * message)>;
using ProcDeviceSetDeviceLostCallback = std::function<void(Device device, DeviceLostCallback&& callback)>;
using ProcDeviceSetUncapturedErrorCallback = std::function<void(Device device, ErrorCallback&& callback)>;

// Handles detailed declarations
HANDLE(Adapter)
	size_t enumerateFeatures(FeatureName * features);
	bool getLimits(SupportedLimits * limits);
	void getProperties(AdapterProperties * properties);
	bool hasFeature(FeatureName feature);
	std::unique_ptr<RequestDeviceCallback> requestDevice(const DeviceDescriptor& descriptor, RequestDeviceCallback&& callback);
	Device requestDevice(const DeviceDescriptor& descriptor);
END

HANDLE(BindGroup)
	void setLabel(char const * label);
END

HANDLE(BindGroupLayout)
	void setLabel(char const * label);
END

HANDLE(Buffer)
	void destroy();
	void const * getConstMappedRange(size_t offset, size_t size);
	BufferMapState getMapState();
	void * getMappedRange(size_t offset, size_t size);
	uint64_t getSize();
	BufferUsage getUsage();
	std::unique_ptr<BufferMapCallback> mapAsync(MapModeFlags mode, size_t offset, size_t size, BufferMapCallback&& callback);
	void setLabel(char const * label);
	void unmap();
END

HANDLE(CommandBuffer)
	void setLabel(char const * label);
END

HANDLE(CommandEncoder)
	ComputePassEncoder beginComputePass(const ComputePassDescriptor& descriptor);
	RenderPassEncoder beginRenderPass(const RenderPassDescriptor& descriptor);
	void clearBuffer(Buffer buffer, uint64_t offset, uint64_t size);
	void copyBufferToBuffer(Buffer source, uint64_t sourceOffset, Buffer destination, uint64_t destinationOffset, uint64_t size);
	void copyBufferToTexture(const ImageCopyBuffer& source, const ImageCopyTexture& destination, const Extent3D& copySize);
	void copyTextureToBuffer(const ImageCopyTexture& source, const ImageCopyBuffer& destination, const Extent3D& copySize);
	void copyTextureToTexture(const ImageCopyTexture& source, const ImageCopyTexture& destination, const Extent3D& copySize);
	CommandBuffer finish(const CommandBufferDescriptor& descriptor);
	void insertDebugMarker(char const * markerLabel);
	void popDebugGroup();
	void pushDebugGroup(char const * groupLabel);
	void resolveQuerySet(QuerySet querySet, uint32_t firstQuery, uint32_t queryCount, Buffer destination, uint64_t destinationOffset);
	void setLabel(char const * label);
	void writeTimestamp(QuerySet querySet, uint32_t queryIndex);
END

HANDLE(ComputePassEncoder)
	void beginPipelineStatisticsQuery(QuerySet querySet, uint32_t queryIndex);
	void dispatchWorkgroups(uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ);
	void dispatchWorkgroupsIndirect(Buffer indirectBuffer, uint64_t indirectOffset);
	void end();
	void endPipelineStatisticsQuery();
	void insertDebugMarker(char const * markerLabel);
	void popDebugGroup();
	void pushDebugGroup(char const * groupLabel);
	void setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets);
	void setLabel(char const * label);
	void setPipeline(ComputePipeline pipeline);
END

HANDLE(ComputePipeline)
	BindGroupLayout getBindGroupLayout(uint32_t groupIndex);
	void setLabel(char const * label);
END

HANDLE(Device)
	BindGroup createBindGroup(const BindGroupDescriptor& descriptor);
	BindGroupLayout createBindGroupLayout(const BindGroupLayoutDescriptor& descriptor);
	Buffer createBuffer(const BufferDescriptor& descriptor);
	CommandEncoder createCommandEncoder(const CommandEncoderDescriptor& descriptor);
	ComputePipeline createComputePipeline(const ComputePipelineDescriptor& descriptor);
	std::unique_ptr<CreateComputePipelineAsyncCallback> createComputePipelineAsync(const ComputePipelineDescriptor& descriptor, CreateComputePipelineAsyncCallback&& callback);
	PipelineLayout createPipelineLayout(const PipelineLayoutDescriptor& descriptor);
	QuerySet createQuerySet(const QuerySetDescriptor& descriptor);
	RenderBundleEncoder createRenderBundleEncoder(const RenderBundleEncoderDescriptor& descriptor);
	RenderPipeline createRenderPipeline(const RenderPipelineDescriptor& descriptor);
	std::unique_ptr<CreateRenderPipelineAsyncCallback> createRenderPipelineAsync(const RenderPipelineDescriptor& descriptor, CreateRenderPipelineAsyncCallback&& callback);
	Sampler createSampler(const SamplerDescriptor& descriptor);
	ShaderModule createShaderModule(const ShaderModuleDescriptor& descriptor);
	SwapChain createSwapChain(Surface surface, const SwapChainDescriptor& descriptor);
	Texture createTexture(const TextureDescriptor& descriptor);
	void destroy();
	size_t enumerateFeatures(FeatureName * features);
	bool getLimits(SupportedLimits * limits);
	Queue getQueue();
	bool hasFeature(FeatureName feature);
	std::unique_ptr<ErrorCallback> popErrorScope(ErrorCallback&& callback);
	void pushErrorScope(ErrorFilter filter);
	std::unique_ptr<DeviceLostCallback> setDeviceLostCallback(DeviceLostCallback&& callback);
	void setLabel(char const * label);
	std::unique_ptr<ErrorCallback> setUncapturedErrorCallback(ErrorCallback&& callback);
END

HANDLE(Instance)
	Surface createSurface(const SurfaceDescriptor& descriptor);
	void processEvents();
	std::unique_ptr<RequestAdapterCallback> requestAdapter(const RequestAdapterOptions& options, RequestAdapterCallback&& callback);
	Adapter requestAdapter(const RequestAdapterOptions& options);
END

HANDLE(PipelineLayout)
	void setLabel(char const * label);
END

HANDLE(QuerySet)
	void destroy();
	uint32_t getCount();
	QueryType getType();
	void setLabel(char const * label);
END

HANDLE(Queue)
	std::unique_ptr<QueueWorkDoneCallback> onSubmittedWorkDone(QueueWorkDoneCallback&& callback);
	void setLabel(char const * label);
	void submit(uint32_t commandCount, CommandBuffer const * commands);
	void submit(const std::vector<WGPUCommandBuffer>& commands);
	void submit(const WGPUCommandBuffer& commands);
	void writeBuffer(Buffer buffer, uint64_t bufferOffset, void const * data, size_t size);
	void writeTexture(const ImageCopyTexture& destination, void const * data, size_t dataSize, const TextureDataLayout& dataLayout, const Extent3D& writeSize);
END

HANDLE(RenderBundle)
END

HANDLE(RenderBundleEncoder)
	void draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
	void drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance);
	void drawIndexedIndirect(Buffer indirectBuffer, uint64_t indirectOffset);
	void drawIndirect(Buffer indirectBuffer, uint64_t indirectOffset);
	RenderBundle finish(const RenderBundleDescriptor& descriptor);
	void insertDebugMarker(char const * markerLabel);
	void popDebugGroup();
	void pushDebugGroup(char const * groupLabel);
	void setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets);
	void setIndexBuffer(Buffer buffer, IndexFormat format, uint64_t offset, uint64_t size);
	void setLabel(char const * label);
	void setPipeline(RenderPipeline pipeline);
	void setVertexBuffer(uint32_t slot, Buffer buffer, uint64_t offset, uint64_t size);
END

HANDLE(RenderPassEncoder)
	void beginOcclusionQuery(uint32_t queryIndex);
	void beginPipelineStatisticsQuery(QuerySet querySet, uint32_t queryIndex);
	void draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
	void drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance);
	void drawIndexedIndirect(Buffer indirectBuffer, uint64_t indirectOffset);
	void drawIndirect(Buffer indirectBuffer, uint64_t indirectOffset);
	void end();
	void endOcclusionQuery();
	void endPipelineStatisticsQuery();
	void executeBundles(uint32_t bundleCount, RenderBundle const * bundles);
	void executeBundles(const std::vector<WGPURenderBundle>& bundles);
	void executeBundles(const WGPURenderBundle& bundles);
	void insertDebugMarker(char const * markerLabel);
	void popDebugGroup();
	void pushDebugGroup(char const * groupLabel);
	void setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets);
	void setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets);
	void setBlendConstant(const Color& color);
	void setIndexBuffer(Buffer buffer, IndexFormat format, uint64_t offset, uint64_t size);
	void setLabel(char const * label);
	void setPipeline(RenderPipeline pipeline);
	void setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
	void setStencilReference(uint32_t reference);
	void setVertexBuffer(uint32_t slot, Buffer buffer, uint64_t offset, uint64_t size);
	void setViewport(float x, float y, float width, float height, float minDepth, float maxDepth);
END

HANDLE(RenderPipeline)
	BindGroupLayout getBindGroupLayout(uint32_t groupIndex);
	void setLabel(char const * label);
END

HANDLE(Sampler)
	void setLabel(char const * label);
END

HANDLE(ShaderModule)
	std::unique_ptr<CompilationInfoCallback> getCompilationInfo(CompilationInfoCallback&& callback);
	void setLabel(char const * label);
END

HANDLE(Surface)
	TextureFormat getPreferredFormat(Adapter adapter);
END

HANDLE(SwapChain)
	TextureView getCurrentTextureView();
	void present();
END

HANDLE(Texture)
	TextureView createView(const TextureViewDescriptor& descriptor);
	void destroy();
	uint32_t getDepthOrArrayLayers();
	TextureDimension getDimension();
	TextureFormat getFormat();
	uint32_t getHeight();
	uint32_t getMipLevelCount();
	uint32_t getSampleCount();
	TextureUsage getUsage();
	uint32_t getWidth();
	void setLabel(char const * label);
END

HANDLE(TextureView)
	void setLabel(char const * label);
END


// Non-member procedures


Instance createInstance(const InstanceDescriptor& descriptor);

#ifdef WEBGPU_CPP_IMPLEMENTATION

Instance createInstance(const InstanceDescriptor& descriptor) {
	return wgpuCreateInstance(&descriptor);
}

// Handles members implementation
// Methods of ChainedStruct
void ChainedStruct::setDefault() {
}

// Methods of ChainedStructOut
void ChainedStructOut::setDefault() {
}

// Methods of AdapterProperties
void AdapterProperties::setDefault() {
}

// Methods of BindGroupEntry
void BindGroupEntry::setDefault() {
	offset = 0;
}

// Methods of BlendComponent
void BlendComponent::setDefault() {
	operation = BlendOperation::Add;
	srcFactor = BlendFactor::One;
	dstFactor = BlendFactor::Zero;
}

// Methods of BufferBindingLayout
void BufferBindingLayout::setDefault() {
	type = BufferBindingType::Uniform;
	hasDynamicOffset = false;
	minBindingSize = 0;
}

// Methods of BufferDescriptor
void BufferDescriptor::setDefault() {
	mappedAtCreation = false;
}

// Methods of Color
void Color::setDefault() {
}

// Methods of CommandBufferDescriptor
void CommandBufferDescriptor::setDefault() {
}

// Methods of CommandEncoderDescriptor
void CommandEncoderDescriptor::setDefault() {
}

// Methods of CompilationMessage
void CompilationMessage::setDefault() {
}

// Methods of ComputePassTimestampWrite
void ComputePassTimestampWrite::setDefault() {
}

// Methods of ConstantEntry
void ConstantEntry::setDefault() {
}

// Methods of Extent3D
void Extent3D::setDefault() {
	height = 1;
	depthOrArrayLayers = 1;
}

// Methods of InstanceDescriptor
void InstanceDescriptor::setDefault() {
}

// Methods of Limits
void Limits::setDefault() {
	maxTextureDimension1D = 0;
	maxTextureDimension2D = 0;
	maxTextureDimension3D = 0;
	maxTextureArrayLayers = 0;
	maxBindGroups = 0;
	maxBindingsPerBindGroup = 0;
	maxDynamicUniformBuffersPerPipelineLayout = 0;
	maxDynamicStorageBuffersPerPipelineLayout = 0;
	maxSampledTexturesPerShaderStage = 0;
	maxSamplersPerShaderStage = 0;
	maxStorageBuffersPerShaderStage = 0;
	maxStorageTexturesPerShaderStage = 0;
	maxUniformBuffersPerShaderStage = 0;
	maxUniformBufferBindingSize = 0;
	maxStorageBufferBindingSize = 0;
	minUniformBufferOffsetAlignment = 64;
	minStorageBufferOffsetAlignment = 16;
	maxVertexBuffers = 0;
	maxBufferSize = 0;
	maxVertexAttributes = 0;
	maxVertexBufferArrayStride = 0;
	maxInterStageShaderComponents = 0;
	maxInterStageShaderVariables = 0;
	maxColorAttachments = 0;
	maxColorAttachmentBytesPerSample = 0;
	maxComputeWorkgroupStorageSize = 0;
	maxComputeInvocationsPerWorkgroup = 0;
	maxComputeWorkgroupSizeX = 0;
	maxComputeWorkgroupSizeY = 0;
	maxComputeWorkgroupSizeZ = 0;
	maxComputeWorkgroupsPerDimension = 0;
}

// Methods of MultisampleState
void MultisampleState::setDefault() {
	count = 1;
	mask = 0xFFFFFFFF;
	alphaToCoverageEnabled = false;
}

// Methods of Origin3D
void Origin3D::setDefault() {
	x = 0;
	y = 0;
	z = 0;
}

// Methods of PipelineLayoutDescriptor
void PipelineLayoutDescriptor::setDefault() {
}

// Methods of PrimitiveDepthClipControl
void PrimitiveDepthClipControl::setDefault() {
	unclippedDepth = false;
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::PrimitiveDepthClipControl;
}

// Methods of PrimitiveState
void PrimitiveState::setDefault() {
	topology = PrimitiveTopology::TriangleList;
	stripIndexFormat = IndexFormat::Undefined;
	frontFace = FrontFace::CCW;
	cullMode = CullMode::None;
}

// Methods of QuerySetDescriptor
void QuerySetDescriptor::setDefault() {
}

// Methods of QueueDescriptor
void QueueDescriptor::setDefault() {
}

// Methods of RenderBundleDescriptor
void RenderBundleDescriptor::setDefault() {
}

// Methods of RenderBundleEncoderDescriptor
void RenderBundleEncoderDescriptor::setDefault() {
	depthStencilFormat = TextureFormat::Undefined;
	depthReadOnly = false;
	stencilReadOnly = false;
	sampleCount = 1;
}

// Methods of RenderPassDepthStencilAttachment
void RenderPassDepthStencilAttachment::setDefault() {
	depthLoadOp = LoadOp::Undefined;
	depthStoreOp = StoreOp::Undefined;
	depthClearValue = 0;
	depthReadOnly = false;
	stencilLoadOp = LoadOp::Undefined;
	stencilStoreOp = StoreOp::Undefined;
	stencilClearValue = 0;
	stencilReadOnly = false;
}

// Methods of RenderPassDescriptorMaxDrawCount
void RenderPassDescriptorMaxDrawCount::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::RenderPassDescriptorMaxDrawCount;
}

// Methods of RenderPassTimestampWrite
void RenderPassTimestampWrite::setDefault() {
}

// Methods of RequestAdapterOptions
void RequestAdapterOptions::setDefault() {
	powerPreference = PowerPreference::Undefined;
	forceFallbackAdapter = false;
}

// Methods of SamplerBindingLayout
void SamplerBindingLayout::setDefault() {
	type = SamplerBindingType::Filtering;
}

// Methods of SamplerDescriptor
void SamplerDescriptor::setDefault() {
	addressModeU = AddressMode::ClampToEdge;
	addressModeV = AddressMode::ClampToEdge;
	addressModeW = AddressMode::ClampToEdge;
	magFilter = FilterMode::Nearest;
	minFilter = FilterMode::Nearest;
	mipmapFilter = MipmapFilterMode::Nearest;
	lodMinClamp = 0;
	lodMaxClamp = 32;
	compare = CompareFunction::Undefined;
}

// Methods of ShaderModuleCompilationHint
void ShaderModuleCompilationHint::setDefault() {
}

// Methods of ShaderModuleSPIRVDescriptor
void ShaderModuleSPIRVDescriptor::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::ShaderModuleSPIRVDescriptor;
}

// Methods of ShaderModuleWGSLDescriptor
void ShaderModuleWGSLDescriptor::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::ShaderModuleWGSLDescriptor;
}

// Methods of StencilFaceState
void StencilFaceState::setDefault() {
	compare = CompareFunction::Always;
	failOp = StencilOperation::Keep;
	depthFailOp = StencilOperation::Keep;
	passOp = StencilOperation::Keep;
}

// Methods of StorageTextureBindingLayout
void StorageTextureBindingLayout::setDefault() {
	access = StorageTextureAccess::WriteOnly;
	format = TextureFormat::Undefined;
	viewDimension = TextureViewDimension::_2D;
}

// Methods of SurfaceDescriptor
void SurfaceDescriptor::setDefault() {
}

// Methods of SurfaceDescriptorFromAndroidNativeWindow
void SurfaceDescriptorFromAndroidNativeWindow::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromAndroidNativeWindow;
}

// Methods of SurfaceDescriptorFromCanvasHTMLSelector
void SurfaceDescriptorFromCanvasHTMLSelector::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromCanvasHTMLSelector;
}

// Methods of SurfaceDescriptorFromMetalLayer
void SurfaceDescriptorFromMetalLayer::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromMetalLayer;
}

// Methods of SurfaceDescriptorFromWaylandSurface
void SurfaceDescriptorFromWaylandSurface::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromWaylandSurface;
}

// Methods of SurfaceDescriptorFromWindowsHWND
void SurfaceDescriptorFromWindowsHWND::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromWindowsHWND;
}

// Methods of SurfaceDescriptorFromXcbWindow
void SurfaceDescriptorFromXcbWindow::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromXcbWindow;
}

// Methods of SurfaceDescriptorFromXlibWindow
void SurfaceDescriptorFromXlibWindow::setDefault() {
	((ChainedStruct*)&chain)->setDefault();
	chain.sType = SType::SurfaceDescriptorFromXlibWindow;
}

// Methods of SwapChainDescriptor
void SwapChainDescriptor::setDefault() {
	format = TextureFormat::Undefined;
}

// Methods of TextureBindingLayout
void TextureBindingLayout::setDefault() {
	sampleType = TextureSampleType::Float;
	viewDimension = TextureViewDimension::_2D;
	multisampled = false;
}

// Methods of TextureDataLayout
void TextureDataLayout::setDefault() {
}

// Methods of TextureViewDescriptor
void TextureViewDescriptor::setDefault() {
	format = TextureFormat::Undefined;
	dimension = TextureViewDimension::Undefined;
	baseMipLevel = 0;
	baseArrayLayer = 0;
	aspect = TextureAspect::All;
}

// Methods of VertexAttribute
void VertexAttribute::setDefault() {
	format = VertexFormat::Undefined;
}

// Methods of BindGroupDescriptor
void BindGroupDescriptor::setDefault() {
}

// Methods of BindGroupLayoutEntry
void BindGroupLayoutEntry::setDefault() {
	((BufferBindingLayout*)&buffer)->setDefault();
	((SamplerBindingLayout*)&sampler)->setDefault();
	((TextureBindingLayout*)&texture)->setDefault();
	((StorageTextureBindingLayout*)&storageTexture)->setDefault();
	buffer.type = BufferBindingType::Undefined;
	sampler.type = SamplerBindingType::Undefined;
	storageTexture.access = StorageTextureAccess::Undefined;
	texture.sampleType = TextureSampleType::Undefined;
	buffer.type = BufferBindingType::Undefined;
	sampler.type = SamplerBindingType::Undefined;
	storageTexture.access = StorageTextureAccess::Undefined;
	texture.sampleType = TextureSampleType::Undefined;
}

// Methods of BlendState
void BlendState::setDefault() {
	((BlendComponent*)&color)->setDefault();
	((BlendComponent*)&alpha)->setDefault();
}

// Methods of CompilationInfo
void CompilationInfo::setDefault() {
}

// Methods of ComputePassDescriptor
void ComputePassDescriptor::setDefault() {
}

// Methods of DepthStencilState
void DepthStencilState::setDefault() {
	format = TextureFormat::Undefined;
	depthWriteEnabled = false;
	depthCompare = CompareFunction::Always;
	stencilReadMask = 0xFFFFFFFF;
	stencilWriteMask = 0xFFFFFFFF;
	depthBias = 0;
	depthBiasSlopeScale = 0;
	depthBiasClamp = 0;
	((StencilFaceState*)&stencilFront)->setDefault();
	((StencilFaceState*)&stencilBack)->setDefault();
}

// Methods of ImageCopyBuffer
void ImageCopyBuffer::setDefault() {
	((TextureDataLayout*)&layout)->setDefault();
}

// Methods of ImageCopyTexture
void ImageCopyTexture::setDefault() {
	mipLevel = 0;
	aspect = TextureAspect::All;
	((Origin3D*)&origin)->setDefault();
}

// Methods of ProgrammableStageDescriptor
void ProgrammableStageDescriptor::setDefault() {
}

// Methods of RenderPassColorAttachment
void RenderPassColorAttachment::setDefault() {
	loadOp = LoadOp::Undefined;
	storeOp = StoreOp::Undefined;
	((Color*)&clearValue)->setDefault();
}

// Methods of RequiredLimits
void RequiredLimits::setDefault() {
	((Limits*)&limits)->setDefault();
}

// Methods of ShaderModuleDescriptor
void ShaderModuleDescriptor::setDefault() {
}

// Methods of SupportedLimits
void SupportedLimits::setDefault() {
	((Limits*)&limits)->setDefault();
}

// Methods of TextureDescriptor
void TextureDescriptor::setDefault() {
	dimension = TextureDimension::_2D;
	format = TextureFormat::Undefined;
	mipLevelCount = 1;
	sampleCount = 1;
	((Extent3D*)&size)->setDefault();
}

// Methods of VertexBufferLayout
void VertexBufferLayout::setDefault() {
	stepMode = VertexStepMode::Vertex;
}

// Methods of BindGroupLayoutDescriptor
void BindGroupLayoutDescriptor::setDefault() {
}

// Methods of ColorTargetState
void ColorTargetState::setDefault() {
	format = TextureFormat::Undefined;
}

// Methods of ComputePipelineDescriptor
void ComputePipelineDescriptor::setDefault() {
	((ProgrammableStageDescriptor*)&compute)->setDefault();
}

// Methods of DeviceDescriptor
void DeviceDescriptor::setDefault() {
	((QueueDescriptor*)&defaultQueue)->setDefault();
}

// Methods of RenderPassDescriptor
void RenderPassDescriptor::setDefault() {
}

// Methods of VertexState
void VertexState::setDefault() {
}

// Methods of FragmentState
void FragmentState::setDefault() {
}

// Methods of RenderPipelineDescriptor
void RenderPipelineDescriptor::setDefault() {
	((VertexState*)&vertex)->setDefault();
	((PrimitiveState*)&primitive)->setDefault();
	((MultisampleState*)&multisample)->setDefault();
}

// Methods of Adapter
size_t Adapter::enumerateFeatures(FeatureName * features) {
	return wgpuAdapterEnumerateFeatures(m_raw, reinterpret_cast<WGPUFeatureName *>(features));
}
bool Adapter::getLimits(SupportedLimits * limits) {
	return wgpuAdapterGetLimits(m_raw, limits);
}
void Adapter::getProperties(AdapterProperties * properties) {
	return wgpuAdapterGetProperties(m_raw, properties);
}
bool Adapter::hasFeature(FeatureName feature) {
	return wgpuAdapterHasFeature(m_raw, static_cast<WGPUFeatureName>(feature));
}
std::unique_ptr<RequestDeviceCallback> Adapter::requestDevice(const DeviceDescriptor& descriptor, RequestDeviceCallback&& callback) {
	auto handle = std::make_unique<RequestDeviceCallback>(callback);
	static auto cCallback = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata) -> void {
		RequestDeviceCallback& callback = *reinterpret_cast<RequestDeviceCallback*>(userdata);
		callback(static_cast<RequestDeviceStatus>(status), device, message);
	};
	wgpuAdapterRequestDevice(m_raw, &descriptor, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}


// Methods of BindGroup
void BindGroup::setLabel(char const * label) {
	return wgpuBindGroupSetLabel(m_raw, label);
}


// Methods of BindGroupLayout
void BindGroupLayout::setLabel(char const * label) {
	return wgpuBindGroupLayoutSetLabel(m_raw, label);
}


// Methods of Buffer
void Buffer::destroy() {
	return wgpuBufferDestroy(m_raw);
}
void const * Buffer::getConstMappedRange(size_t offset, size_t size) {
	return wgpuBufferGetConstMappedRange(m_raw, offset, size);
}
BufferMapState Buffer::getMapState() {
	return static_cast<BufferMapState>(wgpuBufferGetMapState(m_raw));
}
void * Buffer::getMappedRange(size_t offset, size_t size) {
	return wgpuBufferGetMappedRange(m_raw, offset, size);
}
uint64_t Buffer::getSize() {
	return wgpuBufferGetSize(m_raw);
}
BufferUsage Buffer::getUsage() {
	return static_cast<BufferUsage>(wgpuBufferGetUsage(m_raw));
}
std::unique_ptr<BufferMapCallback> Buffer::mapAsync(MapModeFlags mode, size_t offset, size_t size, BufferMapCallback&& callback) {
	auto handle = std::make_unique<BufferMapCallback>(callback);
	static auto cCallback = [](WGPUBufferMapAsyncStatus status, void * userdata) -> void {
		BufferMapCallback& callback = *reinterpret_cast<BufferMapCallback*>(userdata);
		callback(static_cast<BufferMapAsyncStatus>(status));
	};
	wgpuBufferMapAsync(m_raw, static_cast<WGPUMapModeFlags>(mode), offset, size, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
void Buffer::setLabel(char const * label) {
	return wgpuBufferSetLabel(m_raw, label);
}
void Buffer::unmap() {
	return wgpuBufferUnmap(m_raw);
}


// Methods of CommandBuffer
void CommandBuffer::setLabel(char const * label) {
	return wgpuCommandBufferSetLabel(m_raw, label);
}


// Methods of CommandEncoder
ComputePassEncoder CommandEncoder::beginComputePass(const ComputePassDescriptor& descriptor) {
	return wgpuCommandEncoderBeginComputePass(m_raw, &descriptor);
}
RenderPassEncoder CommandEncoder::beginRenderPass(const RenderPassDescriptor& descriptor) {
	return wgpuCommandEncoderBeginRenderPass(m_raw, &descriptor);
}
void CommandEncoder::clearBuffer(Buffer buffer, uint64_t offset, uint64_t size) {
	return wgpuCommandEncoderClearBuffer(m_raw, buffer, offset, size);
}
void CommandEncoder::copyBufferToBuffer(Buffer source, uint64_t sourceOffset, Buffer destination, uint64_t destinationOffset, uint64_t size) {
	return wgpuCommandEncoderCopyBufferToBuffer(m_raw, source, sourceOffset, destination, destinationOffset, size);
}
void CommandEncoder::copyBufferToTexture(const ImageCopyBuffer& source, const ImageCopyTexture& destination, const Extent3D& copySize) {
	return wgpuCommandEncoderCopyBufferToTexture(m_raw, &source, &destination, &copySize);
}
void CommandEncoder::copyTextureToBuffer(const ImageCopyTexture& source, const ImageCopyBuffer& destination, const Extent3D& copySize) {
	return wgpuCommandEncoderCopyTextureToBuffer(m_raw, &source, &destination, &copySize);
}
void CommandEncoder::copyTextureToTexture(const ImageCopyTexture& source, const ImageCopyTexture& destination, const Extent3D& copySize) {
	return wgpuCommandEncoderCopyTextureToTexture(m_raw, &source, &destination, &copySize);
}
CommandBuffer CommandEncoder::finish(const CommandBufferDescriptor& descriptor) {
	return wgpuCommandEncoderFinish(m_raw, &descriptor);
}
void CommandEncoder::insertDebugMarker(char const * markerLabel) {
	return wgpuCommandEncoderInsertDebugMarker(m_raw, markerLabel);
}
void CommandEncoder::popDebugGroup() {
	return wgpuCommandEncoderPopDebugGroup(m_raw);
}
void CommandEncoder::pushDebugGroup(char const * groupLabel) {
	return wgpuCommandEncoderPushDebugGroup(m_raw, groupLabel);
}
void CommandEncoder::resolveQuerySet(QuerySet querySet, uint32_t firstQuery, uint32_t queryCount, Buffer destination, uint64_t destinationOffset) {
	return wgpuCommandEncoderResolveQuerySet(m_raw, querySet, firstQuery, queryCount, destination, destinationOffset);
}
void CommandEncoder::setLabel(char const * label) {
	return wgpuCommandEncoderSetLabel(m_raw, label);
}
void CommandEncoder::writeTimestamp(QuerySet querySet, uint32_t queryIndex) {
	return wgpuCommandEncoderWriteTimestamp(m_raw, querySet, queryIndex);
}


// Methods of ComputePassEncoder
void ComputePassEncoder::beginPipelineStatisticsQuery(QuerySet querySet, uint32_t queryIndex) {
	return wgpuComputePassEncoderBeginPipelineStatisticsQuery(m_raw, querySet, queryIndex);
}
void ComputePassEncoder::dispatchWorkgroups(uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ) {
	return wgpuComputePassEncoderDispatchWorkgroups(m_raw, workgroupCountX, workgroupCountY, workgroupCountZ);
}
void ComputePassEncoder::dispatchWorkgroupsIndirect(Buffer indirectBuffer, uint64_t indirectOffset) {
	return wgpuComputePassEncoderDispatchWorkgroupsIndirect(m_raw, indirectBuffer, indirectOffset);
}
void ComputePassEncoder::end() {
	return wgpuComputePassEncoderEnd(m_raw);
}
void ComputePassEncoder::endPipelineStatisticsQuery() {
	return wgpuComputePassEncoderEndPipelineStatisticsQuery(m_raw);
}
void ComputePassEncoder::insertDebugMarker(char const * markerLabel) {
	return wgpuComputePassEncoderInsertDebugMarker(m_raw, markerLabel);
}
void ComputePassEncoder::popDebugGroup() {
	return wgpuComputePassEncoderPopDebugGroup(m_raw);
}
void ComputePassEncoder::pushDebugGroup(char const * groupLabel) {
	return wgpuComputePassEncoderPushDebugGroup(m_raw, groupLabel);
}
void ComputePassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets) {
	return wgpuComputePassEncoderSetBindGroup(m_raw, groupIndex, group, dynamicOffsetCount, dynamicOffsets);
}
void ComputePassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets) {
	return wgpuComputePassEncoderSetBindGroup(m_raw, groupIndex, group, static_cast<uint32_t>(dynamicOffsets.size()), dynamicOffsets.data());
}
void ComputePassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets) {
	return wgpuComputePassEncoderSetBindGroup(m_raw, groupIndex, group, 1, &dynamicOffsets);
}
void ComputePassEncoder::setLabel(char const * label) {
	return wgpuComputePassEncoderSetLabel(m_raw, label);
}
void ComputePassEncoder::setPipeline(ComputePipeline pipeline) {
	return wgpuComputePassEncoderSetPipeline(m_raw, pipeline);
}


// Methods of ComputePipeline
BindGroupLayout ComputePipeline::getBindGroupLayout(uint32_t groupIndex) {
	return wgpuComputePipelineGetBindGroupLayout(m_raw, groupIndex);
}
void ComputePipeline::setLabel(char const * label) {
	return wgpuComputePipelineSetLabel(m_raw, label);
}


// Methods of Device
BindGroup Device::createBindGroup(const BindGroupDescriptor& descriptor) {
	return wgpuDeviceCreateBindGroup(m_raw, &descriptor);
}
BindGroupLayout Device::createBindGroupLayout(const BindGroupLayoutDescriptor& descriptor) {
	return wgpuDeviceCreateBindGroupLayout(m_raw, &descriptor);
}
Buffer Device::createBuffer(const BufferDescriptor& descriptor) {
	return wgpuDeviceCreateBuffer(m_raw, &descriptor);
}
CommandEncoder Device::createCommandEncoder(const CommandEncoderDescriptor& descriptor) {
	return wgpuDeviceCreateCommandEncoder(m_raw, &descriptor);
}
ComputePipeline Device::createComputePipeline(const ComputePipelineDescriptor& descriptor) {
	return wgpuDeviceCreateComputePipeline(m_raw, &descriptor);
}
std::unique_ptr<CreateComputePipelineAsyncCallback> Device::createComputePipelineAsync(const ComputePipelineDescriptor& descriptor, CreateComputePipelineAsyncCallback&& callback) {
	auto handle = std::make_unique<CreateComputePipelineAsyncCallback>(callback);
	static auto cCallback = [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline, char const * message, void * userdata) -> void {
		CreateComputePipelineAsyncCallback& callback = *reinterpret_cast<CreateComputePipelineAsyncCallback*>(userdata);
		callback(static_cast<CreatePipelineAsyncStatus>(status), pipeline, message);
	};
	wgpuDeviceCreateComputePipelineAsync(m_raw, &descriptor, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
PipelineLayout Device::createPipelineLayout(const PipelineLayoutDescriptor& descriptor) {
	return wgpuDeviceCreatePipelineLayout(m_raw, &descriptor);
}
QuerySet Device::createQuerySet(const QuerySetDescriptor& descriptor) {
	return wgpuDeviceCreateQuerySet(m_raw, &descriptor);
}
RenderBundleEncoder Device::createRenderBundleEncoder(const RenderBundleEncoderDescriptor& descriptor) {
	return wgpuDeviceCreateRenderBundleEncoder(m_raw, &descriptor);
}
RenderPipeline Device::createRenderPipeline(const RenderPipelineDescriptor& descriptor) {
	return wgpuDeviceCreateRenderPipeline(m_raw, &descriptor);
}
std::unique_ptr<CreateRenderPipelineAsyncCallback> Device::createRenderPipelineAsync(const RenderPipelineDescriptor& descriptor, CreateRenderPipelineAsyncCallback&& callback) {
	auto handle = std::make_unique<CreateRenderPipelineAsyncCallback>(callback);
	static auto cCallback = [](WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline, char const * message, void * userdata) -> void {
		CreateRenderPipelineAsyncCallback& callback = *reinterpret_cast<CreateRenderPipelineAsyncCallback*>(userdata);
		callback(static_cast<CreatePipelineAsyncStatus>(status), pipeline, message);
	};
	wgpuDeviceCreateRenderPipelineAsync(m_raw, &descriptor, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
Sampler Device::createSampler(const SamplerDescriptor& descriptor) {
	return wgpuDeviceCreateSampler(m_raw, &descriptor);
}
ShaderModule Device::createShaderModule(const ShaderModuleDescriptor& descriptor) {
	return wgpuDeviceCreateShaderModule(m_raw, &descriptor);
}
SwapChain Device::createSwapChain(Surface surface, const SwapChainDescriptor& descriptor) {
	return wgpuDeviceCreateSwapChain(m_raw, surface, &descriptor);
}
Texture Device::createTexture(const TextureDescriptor& descriptor) {
	return wgpuDeviceCreateTexture(m_raw, &descriptor);
}
void Device::destroy() {
	return wgpuDeviceDestroy(m_raw);
}
size_t Device::enumerateFeatures(FeatureName * features) {
	return wgpuDeviceEnumerateFeatures(m_raw, reinterpret_cast<WGPUFeatureName *>(features));
}
bool Device::getLimits(SupportedLimits * limits) {
	return wgpuDeviceGetLimits(m_raw, limits);
}
Queue Device::getQueue() {
	return wgpuDeviceGetQueue(m_raw);
}
bool Device::hasFeature(FeatureName feature) {
	return wgpuDeviceHasFeature(m_raw, static_cast<WGPUFeatureName>(feature));
}
std::unique_ptr<ErrorCallback> Device::popErrorScope(ErrorCallback&& callback) {
	auto handle = std::make_unique<ErrorCallback>(callback);
	static auto cCallback = [](WGPUErrorType type, char const * message, void * userdata) -> void {
		ErrorCallback& callback = *reinterpret_cast<ErrorCallback*>(userdata);
		callback(static_cast<ErrorType>(type), message);
	};
	wgpuDevicePopErrorScope(m_raw, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
void Device::pushErrorScope(ErrorFilter filter) {
	return wgpuDevicePushErrorScope(m_raw, static_cast<WGPUErrorFilter>(filter));
}
std::unique_ptr<DeviceLostCallback> Device::setDeviceLostCallback(DeviceLostCallback&& callback) {
	auto handle = std::make_unique<DeviceLostCallback>(callback);
	static auto cCallback = [](WGPUDeviceLostReason reason, char const * message, void * userdata) -> void {
		DeviceLostCallback& callback = *reinterpret_cast<DeviceLostCallback*>(userdata);
		callback(static_cast<DeviceLostReason>(reason), message);
	};
	wgpuDeviceSetDeviceLostCallback(m_raw, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
void Device::setLabel(char const * label) {
	return wgpuDeviceSetLabel(m_raw, label);
}
std::unique_ptr<ErrorCallback> Device::setUncapturedErrorCallback(ErrorCallback&& callback) {
	auto handle = std::make_unique<ErrorCallback>(callback);
	static auto cCallback = [](WGPUErrorType type, char const * message, void * userdata) -> void {
		ErrorCallback& callback = *reinterpret_cast<ErrorCallback*>(userdata);
		callback(static_cast<ErrorType>(type), message);
	};
	wgpuDeviceSetUncapturedErrorCallback(m_raw, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}


// Methods of Instance
Surface Instance::createSurface(const SurfaceDescriptor& descriptor) {
	return wgpuInstanceCreateSurface(m_raw, &descriptor);
}
void Instance::processEvents() {
	return wgpuInstanceProcessEvents(m_raw);
}
std::unique_ptr<RequestAdapterCallback> Instance::requestAdapter(const RequestAdapterOptions& options, RequestAdapterCallback&& callback) {
	auto handle = std::make_unique<RequestAdapterCallback>(callback);
	static auto cCallback = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * userdata) -> void {
		RequestAdapterCallback& callback = *reinterpret_cast<RequestAdapterCallback*>(userdata);
		callback(static_cast<RequestAdapterStatus>(status), adapter, message);
	};
	wgpuInstanceRequestAdapter(m_raw, &options, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}


// Methods of PipelineLayout
void PipelineLayout::setLabel(char const * label) {
	return wgpuPipelineLayoutSetLabel(m_raw, label);
}


// Methods of QuerySet
void QuerySet::destroy() {
	return wgpuQuerySetDestroy(m_raw);
}
uint32_t QuerySet::getCount() {
	return wgpuQuerySetGetCount(m_raw);
}
QueryType QuerySet::getType() {
	return static_cast<QueryType>(wgpuQuerySetGetType(m_raw));
}
void QuerySet::setLabel(char const * label) {
	return wgpuQuerySetSetLabel(m_raw, label);
}


// Methods of Queue
std::unique_ptr<QueueWorkDoneCallback> Queue::onSubmittedWorkDone(QueueWorkDoneCallback&& callback) {
	auto handle = std::make_unique<QueueWorkDoneCallback>(callback);
	static auto cCallback = [](WGPUQueueWorkDoneStatus status, void * userdata) -> void {
		QueueWorkDoneCallback& callback = *reinterpret_cast<QueueWorkDoneCallback*>(userdata);
		callback(static_cast<QueueWorkDoneStatus>(status));
	};
	wgpuQueueOnSubmittedWorkDone(m_raw, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
void Queue::setLabel(char const * label) {
	return wgpuQueueSetLabel(m_raw, label);
}
void Queue::submit(uint32_t commandCount, CommandBuffer const * commands) {
	return wgpuQueueSubmit(m_raw, commandCount, reinterpret_cast<WGPUCommandBuffer const *>(commands));
}
void Queue::submit(const std::vector<WGPUCommandBuffer>& commands) {
	return wgpuQueueSubmit(m_raw, static_cast<uint32_t>(commands.size()), commands.data());
}
void Queue::submit(const WGPUCommandBuffer& commands) {
	return wgpuQueueSubmit(m_raw, 1, &commands);
}
void Queue::writeBuffer(Buffer buffer, uint64_t bufferOffset, void const * data, size_t size) {
	return wgpuQueueWriteBuffer(m_raw, buffer, bufferOffset, data, size);
}
void Queue::writeTexture(const ImageCopyTexture& destination, void const * data, size_t dataSize, const TextureDataLayout& dataLayout, const Extent3D& writeSize) {
	return wgpuQueueWriteTexture(m_raw, &destination, data, dataSize, &dataLayout, &writeSize);
}


// Methods of RenderBundle


// Methods of RenderBundleEncoder
void RenderBundleEncoder::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
	return wgpuRenderBundleEncoderDraw(m_raw, vertexCount, instanceCount, firstVertex, firstInstance);
}
void RenderBundleEncoder::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) {
	return wgpuRenderBundleEncoderDrawIndexed(m_raw, indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
}
void RenderBundleEncoder::drawIndexedIndirect(Buffer indirectBuffer, uint64_t indirectOffset) {
	return wgpuRenderBundleEncoderDrawIndexedIndirect(m_raw, indirectBuffer, indirectOffset);
}
void RenderBundleEncoder::drawIndirect(Buffer indirectBuffer, uint64_t indirectOffset) {
	return wgpuRenderBundleEncoderDrawIndirect(m_raw, indirectBuffer, indirectOffset);
}
RenderBundle RenderBundleEncoder::finish(const RenderBundleDescriptor& descriptor) {
	return wgpuRenderBundleEncoderFinish(m_raw, &descriptor);
}
void RenderBundleEncoder::insertDebugMarker(char const * markerLabel) {
	return wgpuRenderBundleEncoderInsertDebugMarker(m_raw, markerLabel);
}
void RenderBundleEncoder::popDebugGroup() {
	return wgpuRenderBundleEncoderPopDebugGroup(m_raw);
}
void RenderBundleEncoder::pushDebugGroup(char const * groupLabel) {
	return wgpuRenderBundleEncoderPushDebugGroup(m_raw, groupLabel);
}
void RenderBundleEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets) {
	return wgpuRenderBundleEncoderSetBindGroup(m_raw, groupIndex, group, dynamicOffsetCount, dynamicOffsets);
}
void RenderBundleEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets) {
	return wgpuRenderBundleEncoderSetBindGroup(m_raw, groupIndex, group, static_cast<uint32_t>(dynamicOffsets.size()), dynamicOffsets.data());
}
void RenderBundleEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets) {
	return wgpuRenderBundleEncoderSetBindGroup(m_raw, groupIndex, group, 1, &dynamicOffsets);
}
void RenderBundleEncoder::setIndexBuffer(Buffer buffer, IndexFormat format, uint64_t offset, uint64_t size) {
	return wgpuRenderBundleEncoderSetIndexBuffer(m_raw, buffer, static_cast<WGPUIndexFormat>(format), offset, size);
}
void RenderBundleEncoder::setLabel(char const * label) {
	return wgpuRenderBundleEncoderSetLabel(m_raw, label);
}
void RenderBundleEncoder::setPipeline(RenderPipeline pipeline) {
	return wgpuRenderBundleEncoderSetPipeline(m_raw, pipeline);
}
void RenderBundleEncoder::setVertexBuffer(uint32_t slot, Buffer buffer, uint64_t offset, uint64_t size) {
	return wgpuRenderBundleEncoderSetVertexBuffer(m_raw, slot, buffer, offset, size);
}


// Methods of RenderPassEncoder
void RenderPassEncoder::beginOcclusionQuery(uint32_t queryIndex) {
	return wgpuRenderPassEncoderBeginOcclusionQuery(m_raw, queryIndex);
}
void RenderPassEncoder::beginPipelineStatisticsQuery(QuerySet querySet, uint32_t queryIndex) {
	return wgpuRenderPassEncoderBeginPipelineStatisticsQuery(m_raw, querySet, queryIndex);
}
void RenderPassEncoder::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
	return wgpuRenderPassEncoderDraw(m_raw, vertexCount, instanceCount, firstVertex, firstInstance);
}
void RenderPassEncoder::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) {
	return wgpuRenderPassEncoderDrawIndexed(m_raw, indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
}
void RenderPassEncoder::drawIndexedIndirect(Buffer indirectBuffer, uint64_t indirectOffset) {
	return wgpuRenderPassEncoderDrawIndexedIndirect(m_raw, indirectBuffer, indirectOffset);
}
void RenderPassEncoder::drawIndirect(Buffer indirectBuffer, uint64_t indirectOffset) {
	return wgpuRenderPassEncoderDrawIndirect(m_raw, indirectBuffer, indirectOffset);
}
void RenderPassEncoder::end() {
	return wgpuRenderPassEncoderEnd(m_raw);
}
void RenderPassEncoder::endOcclusionQuery() {
	return wgpuRenderPassEncoderEndOcclusionQuery(m_raw);
}
void RenderPassEncoder::endPipelineStatisticsQuery() {
	return wgpuRenderPassEncoderEndPipelineStatisticsQuery(m_raw);
}
void RenderPassEncoder::executeBundles(uint32_t bundleCount, RenderBundle const * bundles) {
	return wgpuRenderPassEncoderExecuteBundles(m_raw, bundleCount, reinterpret_cast<WGPURenderBundle const *>(bundles));
}
void RenderPassEncoder::executeBundles(const std::vector<WGPURenderBundle>& bundles) {
	return wgpuRenderPassEncoderExecuteBundles(m_raw, static_cast<uint32_t>(bundles.size()), bundles.data());
}
void RenderPassEncoder::executeBundles(const WGPURenderBundle& bundles) {
	return wgpuRenderPassEncoderExecuteBundles(m_raw, 1, &bundles);
}
void RenderPassEncoder::insertDebugMarker(char const * markerLabel) {
	return wgpuRenderPassEncoderInsertDebugMarker(m_raw, markerLabel);
}
void RenderPassEncoder::popDebugGroup() {
	return wgpuRenderPassEncoderPopDebugGroup(m_raw);
}
void RenderPassEncoder::pushDebugGroup(char const * groupLabel) {
	return wgpuRenderPassEncoderPushDebugGroup(m_raw, groupLabel);
}
void RenderPassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, uint32_t dynamicOffsetCount, uint32_t const * dynamicOffsets) {
	return wgpuRenderPassEncoderSetBindGroup(m_raw, groupIndex, group, dynamicOffsetCount, dynamicOffsets);
}
void RenderPassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const std::vector<uint32_t>& dynamicOffsets) {
	return wgpuRenderPassEncoderSetBindGroup(m_raw, groupIndex, group, static_cast<uint32_t>(dynamicOffsets.size()), dynamicOffsets.data());
}
void RenderPassEncoder::setBindGroup(uint32_t groupIndex, BindGroup group, const uint32_t& dynamicOffsets) {
	return wgpuRenderPassEncoderSetBindGroup(m_raw, groupIndex, group, 1, &dynamicOffsets);
}
void RenderPassEncoder::setBlendConstant(const Color& color) {
	return wgpuRenderPassEncoderSetBlendConstant(m_raw, &color);
}
void RenderPassEncoder::setIndexBuffer(Buffer buffer, IndexFormat format, uint64_t offset, uint64_t size) {
	return wgpuRenderPassEncoderSetIndexBuffer(m_raw, buffer, static_cast<WGPUIndexFormat>(format), offset, size);
}
void RenderPassEncoder::setLabel(char const * label) {
	return wgpuRenderPassEncoderSetLabel(m_raw, label);
}
void RenderPassEncoder::setPipeline(RenderPipeline pipeline) {
	return wgpuRenderPassEncoderSetPipeline(m_raw, pipeline);
}
void RenderPassEncoder::setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
	return wgpuRenderPassEncoderSetScissorRect(m_raw, x, y, width, height);
}
void RenderPassEncoder::setStencilReference(uint32_t reference) {
	return wgpuRenderPassEncoderSetStencilReference(m_raw, reference);
}
void RenderPassEncoder::setVertexBuffer(uint32_t slot, Buffer buffer, uint64_t offset, uint64_t size) {
	return wgpuRenderPassEncoderSetVertexBuffer(m_raw, slot, buffer, offset, size);
}
void RenderPassEncoder::setViewport(float x, float y, float width, float height, float minDepth, float maxDepth) {
	return wgpuRenderPassEncoderSetViewport(m_raw, x, y, width, height, minDepth, maxDepth);
}


// Methods of RenderPipeline
BindGroupLayout RenderPipeline::getBindGroupLayout(uint32_t groupIndex) {
	return wgpuRenderPipelineGetBindGroupLayout(m_raw, groupIndex);
}
void RenderPipeline::setLabel(char const * label) {
	return wgpuRenderPipelineSetLabel(m_raw, label);
}


// Methods of Sampler
void Sampler::setLabel(char const * label) {
	return wgpuSamplerSetLabel(m_raw, label);
}


// Methods of ShaderModule
std::unique_ptr<CompilationInfoCallback> ShaderModule::getCompilationInfo(CompilationInfoCallback&& callback) {
	auto handle = std::make_unique<CompilationInfoCallback>(callback);
	static auto cCallback = [](WGPUCompilationInfoRequestStatus status, WGPUCompilationInfo const * compilationInfo, void * userdata) -> void {
		CompilationInfoCallback& callback = *reinterpret_cast<CompilationInfoCallback*>(userdata);
		callback(static_cast<CompilationInfoRequestStatus>(status), *reinterpret_cast<CompilationInfo const *>(compilationInfo));
	};
	wgpuShaderModuleGetCompilationInfo(m_raw, cCallback, reinterpret_cast<void*>(handle.get()));
	return handle;
}
void ShaderModule::setLabel(char const * label) {
	return wgpuShaderModuleSetLabel(m_raw, label);
}


// Methods of Surface
TextureFormat Surface::getPreferredFormat(Adapter adapter) {
	return static_cast<TextureFormat>(wgpuSurfaceGetPreferredFormat(m_raw, adapter));
}


// Methods of SwapChain
TextureView SwapChain::getCurrentTextureView() {
	return wgpuSwapChainGetCurrentTextureView(m_raw);
}
void SwapChain::present() {
	return wgpuSwapChainPresent(m_raw);
}


// Methods of Texture
TextureView Texture::createView(const TextureViewDescriptor& descriptor) {
	return wgpuTextureCreateView(m_raw, &descriptor);
}
void Texture::destroy() {
	return wgpuTextureDestroy(m_raw);
}
uint32_t Texture::getDepthOrArrayLayers() {
	return wgpuTextureGetDepthOrArrayLayers(m_raw);
}
TextureDimension Texture::getDimension() {
	return static_cast<TextureDimension>(wgpuTextureGetDimension(m_raw));
}
TextureFormat Texture::getFormat() {
	return static_cast<TextureFormat>(wgpuTextureGetFormat(m_raw));
}
uint32_t Texture::getHeight() {
	return wgpuTextureGetHeight(m_raw);
}
uint32_t Texture::getMipLevelCount() {
	return wgpuTextureGetMipLevelCount(m_raw);
}
uint32_t Texture::getSampleCount() {
	return wgpuTextureGetSampleCount(m_raw);
}
TextureUsage Texture::getUsage() {
	return static_cast<TextureUsage>(wgpuTextureGetUsage(m_raw));
}
uint32_t Texture::getWidth() {
	return wgpuTextureGetWidth(m_raw);
}
void Texture::setLabel(char const * label) {
	return wgpuTextureSetLabel(m_raw, label);
}


// Methods of TextureView
void TextureView::setLabel(char const * label) {
	return wgpuTextureViewSetLabel(m_raw, label);
}



// Extra implementations
Adapter Instance::requestAdapter(const RequestAdapterOptions& options) {
	Adapter adapter = nullptr;
	bool requestEnded = false;
	
	auto onAdapterRequestEnded = [&adapter, &requestEnded](RequestAdapterStatus status, Adapter _adapter, char const * message) {
		if (status == RequestAdapterStatus::Success) {
			adapter = _adapter;
		} else {
			std::cout << "Could not get WebGPU adapter: " << message << std::endl;
		}
		requestEnded = true;
	};

	requestAdapter(options, onAdapterRequestEnded);

	assert(requestEnded);
	return adapter;
}

Device Adapter::requestDevice(const DeviceDescriptor& descriptor) {
	WGPUDevice device = nullptr;
	bool requestEnded = false;

	auto onDeviceRequestEnded = [&device, &requestEnded](RequestDeviceStatus status, Device _device, char const * message) {
		if (status == RequestDeviceStatus::Success) {
			device = _device;
		} else {
			std::cout << "Could not get WebGPU adapter: " << message << std::endl;
		}
		requestEnded = true;
	};

	requestDevice(descriptor, onDeviceRequestEnded);

	assert(requestEnded);
	return device;
}

#endif // WEBGPU_CPP_IMPLEMENTATION

#undef HANDLE
#undef DESCRIPTOR
#undef ENUM
#undef ENUM_ENTRY
#undef END

} // namespace wgpu
